'''
Created on 14/04/2013

@author: belentwi
'''
from flask import Blueprint
from flask import request, flash
from flask import render_template
from flask import redirect
from flask import url_for


from app import db
from app.wtforms.proyecto_forms import ProyectoBuscar
from app.wtforms.proyecto_forms import ProyectoCrear
from app.wtforms.proyecto_forms import ProyectoModificar
from app.wtforms.proyecto_forms import ProyectoMiembros
from app.wtforms.proyecto_forms import ProyectoConsultar
from app.models.proyecto import Proyecto
from app.models.fase import Fase
from app.models.entidad import Entidad
from app.models.usuario import Usuario
from app.models.rol import Rol
from app.models.permiso import Permiso
from app.security import g 
from app.security import permission

mod = Blueprint('proyectos', __name__, url_prefix='/proyecto')



@mod.route('/administracion/', methods=['GET', 'POST'])
@permission('ADMINISTRACION_PROYECTOS')
def administracion_proyecto():
       
    
    """
        Muestra en pantalla los proyectos que existen en la base de datos.
        
        @param filtros: los filtros segun los cuales se mostraran los proyectos.
        @return: listado de los proyectos segun los filtros indicados.
    """
    
   
    form = ProyectoBuscar(request.form)   
          
    nombreFilter = form.nombre.data
    liderFilter = form.lider.data
    estadoFilter = form.estado.data    
    entidadFilter = form.entidad.data
        
    if(nombreFilter == None):
        nombreFilter = ''         
    if(liderFilter == None):  
        liderFilter = ''
    if(estadoFilter == None):  
        estadoFilter = ''
    if(entidadFilter == None):
        entidadFilter = '' 
           
       
    rolAdministrador = db.session.query(Rol).filter_by(nombre = 'Administrador de Sistema').first()

    if rolAdministrador in g.user.roles: 
        proyectos = Proyecto.query.filter(Proyecto.nombre.like('%'+nombreFilter+'%' ), Proyecto.estado.like('%'+estadoFilter+'%' ) ).join(Entidad).filter(Entidad.nombre.like('%' + entidadFilter + '%')).join(Usuario).filter(Usuario.nombre.like('%' + liderFilter + '%'))
    else:      
        proyectos = Proyecto.query.filter(Proyecto.id == g.proyecto.id ).join(Entidad).filter(Entidad.nombre.like('%' + entidadFilter + '%')).join(Usuario).filter(Usuario.nombre.like('%' + liderFilter + '%'))

        proyectos = proyectos.all()
            
    return render_template('proyecto/administracion_proyecto.html', form = form, proyectos = proyectos)
    


@mod.route('/crear/', methods=['GET', 'POST'])
def crear_proyecto():
    """
        Muestra en pantalla el formulario de creacion de proyectos, valida los datos ingresados por
        el usuario, hace las validaciones de que el nombre del nuevo proyecto no exista en el
        sistema y se hayan ingresado los datos obligatorios. Luego almacena en base de datos.
    """
  
    if(verificar_autorizacion( g.user,  g.proyecto, 'CREAR_PROYECTO')): 
        
        choices = []
        
        rolLider = db.session.query(Rol).filter_by(nombre = 'Lider Proyecto').first()
        
        lideres = db.session.query(Usuario).filter(Usuario.roles.contains(rolLider), Usuario.estado != 'INACTIVO')
        lideres.all()
          
        for lider in lideres:
            choices.append((str(lider.id), lider.nombre))
    
        form = ProyectoCrear(request.form)
        form.lideres.choices = choices
      
        #obtenemos todos los proyectos del sistema
        proyectos = Proyecto.query.all()
               
        if form.validate_on_submit():
        
            liderProyecto = Usuario.query.get(int(form.lideres.data))            
            
            
            nombre = form.nombre.data            
            #verificamos que el nombre del proyecto sea unico
            contN=0 
            for proy in proyectos:
                if proy.nombre == nombre:
                    contN=contN+1
            
            # Si ya existe el nombre, no permitimos la creacion           
            if contN != 0:
                flash("El nombre del Proyecto ya existe, ingrese otro", 'error-message')
                # Redirigimos a la pagina de creacion
                return redirect(url_for('proyectos.crear_proyecto'))
            
            estado = 'Pendiente'
            costo = 0
            presupuesto = int(form.presupuesto.data)
                                        
            fecha_inicio = None
            fecha_fin = None
            if form.fecha_inicio.data != None and form.fecha_inicio.data != '':
                if form.fecha_fin.data  != None and form.fecha_fin.data  != '':
                    fecha_inicio = form.fecha_inicio.data
                    fecha_fin = form.fecha_fin.data
                    if fecha_inicio > fecha_fin:
                        flash("La fecha inicial debe ser menor a la fecha final", 'error-message')
                        # Redirigimos a la pagina de creacion
                        return redirect(url_for('proyectos.crear_proyecto')) 
           
            lider = liderProyecto
            entidad = Entidad(nombre)  
               
            
            proyecto = Proyecto(nombre, estado, costo, presupuesto, fecha_inicio, fecha_fin, liderProyecto, entidad)
            db.session.add(proyecto)
            db.session.commit()
            flash('El proyecto ha sido registrado con exito')
            return redirect(url_for('proyectos.administracion_proyecto'))
        return render_template("proyecto/crear_proyecto.html", form =  form)
    else:
        flash('NO TIENE PERMISOS PARA CREAR PROYECTOS') 
        return redirect(url_for('proyectos.administracion_proyecto'))



@mod.route('/eliminar/<proyecto>/', methods=['GET', 'POST'])
def eliminar_proyecto(proyecto):
    """
        Muestra en pantalla el formulario de eliminacion de proyectos, se pide la confimacion del usuario 
        y se elimina el proyecto.
        
        @param proyecto: id del proyecto que se desea eliminar.
    """
            
    if(verificar_autorizacion(g.user, g.proyecto,  'ELIMINAR')):
        proyecto_seleccionado = Proyecto.query.filter_by(id=proyecto).first()
        
        if(proyecto_seleccionado.estado != 'Cancelado' and proyecto_seleccionado.estado != 'Finalizado'):
            proyecto_seleccionado.estado = 'Cancelado' 
            db.session.add(proyecto_seleccionado)
            db.session.commit()
            flash('Se ha eliminado el proyecto exitosamente')
            
        else:
            flash('El proyecto ya ha sido eliminado  o finalizado')        
            
        return redirect(url_for('proyectos.administracion_proyecto'))
    
    else:
        flash('NO TIENE PERMISOS PARA ELIMINAR EL PROYECTO') 
        return redirect(url_for('proyectos.administracion_proyecto'))


@mod.route('/finalizar/<proyecto>/', methods=['GET', 'POST'])
def finalizar_proyecto(proyecto):
    """
        Muestra en pantalla el formulario de finalizacion de proyectos, se pide la confimacion del usuario 
        y se finaliza el proyecto.
        
        @param proyecto: id del proyecto que se desea finalizar.
    """
            
    if(verificar_autorizacion(g.user, g.proyecto,  'MODIFICAR')):
        proyecto_seleccionado = Proyecto.query.filter_by(id=proyecto).first()
        
        
        if(proyecto_seleccionado.estado == 'Activo'):
            fases = proyecto_seleccionado.fases
            
            bandera = True
            for fase in fases:
                if(fase.estado != 'Finalizada'):
                    bandera = False
            
            if(bandera):                
                proyecto_seleccionado.estado = 'Finalizado' 
                
                db.session.add(proyecto_seleccionado)
                db.session.commit()
                flash('Se ha finalizado el proyecto exitosamente')
            else:
                flash('No se puede finalizar el proyecto, cuenta con fases que no han sido finalizadas')
            
        else:
            flash('El proyecto no puede ser finalizado, no se encuentra en el estado Activo')        
            
        return redirect(url_for('proyectos.administracion_proyecto'))
    
    else:
        flash('NO TIENE PERMISOS PARA FINALIZAR EL PROYECTO') 
        return redirect(url_for('proyectos.administracion_proyecto'))









@mod.route('/modificar/<proyecto>/', methods=['GET', 'POST'])
def modificar_proyecto(proyecto):
    
    """
        Muestra en pantalla el formulario de modificacion de proyectos.
    
        @param proyecto:  id del proyecto que se desea modificar.
        @return: redirige a la pagina de Administracion de Proyectos.  
    """
    
    
    if(verificar_autorizacion(g.user, g.proyecto,  'MODIFICAR')):         
        
        proyecto_seleccionado = Proyecto.query.filter_by(id=proyecto).first()
        
        if(proyecto_seleccionado.estado != 'Finalizado' and proyecto_seleccionado.estado != 'Cancelado' ):        
        
            rolLider = db.session.query(Rol).filter_by(nombre = 'Lider Proyecto').first()
            
            lideres = db.session.query(Usuario).filter(Usuario.roles.contains(rolLider), Usuario.estado != 'INACTIVO', Usuario.id != proyecto_seleccionado.lider_id)
            lideres.all()
            liderProyecto = Usuario.query.get(proyecto_seleccionado.lider_id)
            
            choicesLideres = []
            choicesLideres.append((str(liderProyecto.id), liderProyecto.nombre))
            
            for lider in lideres:
                choicesLideres.append((str(lider.id), lider.nombre))
           
            form = ProyectoModificar(request.form)           
                        
            if proyecto_seleccionado.estado == 'Pendiente': 
                choicesEstados = (('1','Pendiente'), ('2', 'Activo'))
                form.estado.choices = choicesEstados
            elif proyecto_seleccionado.estado == 'Activo': 
                choicesEstados = (('1','Activo'), ('1','Activo'))
                form.estado.choices = choicesEstados
           
            #obtenemos todos los proyectos del sistema
            proyectos = Proyecto.query.all()
                
            form.lideres.choices = choicesLideres
            if form.validate_on_submit():            
                
                proyecto_seleccionado.nombre = form.nombre.data            
                #verificamos que el nombre del proyecto sea unico
                contN=0 
                for proy in proyectos:
                    if proy.id != proyecto_seleccionado.id:
                        if proy.nombre == proyecto_seleccionado.nombre:
                            contN=contN+1
            
                # Si ya existe el nombre, no permitimos la creacion           
                if contN != 0:
                    flash("El nombre del Proyecto ya existe, ingrese otro", 'error-message')
                    # Redirigimos a la pagina de creacion
                    return redirect(url_for('proyectos.crear_proyecto'))
                
                posicionEstado = int(form.estado.data)            
                proyecto_seleccionado.estado =  choicesEstados[posicionEstado-1][1]
                
                proyecto_seleccionado.costo = form.costo.data               
                proyecto_seleccionado.presupuesto = form.presupuesto.data
                
                if form.fecha_inicio.data != None and form.fecha_inicio.data != '':
                    if form.fecha_fin.data  != None and form.fecha_fin.data  != '':
                        proyecto_seleccionado.fecha_inicio = form.fecha_inicio.data
                        proyecto_seleccionado.fecha_fin = form.fecha_fin.data
                        if proyecto_seleccionado.fecha_inicio > proyecto_seleccionado.fecha_fin:
                            flash("La fecha inicial debe ser menor a la fecha final", 'error-message')
                            # Redirigimos a la pagina de creacion
                            return redirect(url_for('proyectos.administracion_proyecto')) 
    
                liderProyecto = Usuario.query.get(int(form.lideres.data))            
                proyecto_seleccionado.lider = liderProyecto    
                   
                db.session.add(proyecto_seleccionado)
                db.session.commit()
                flash('El proyecto ha sido registrado con exito')
                return redirect(url_for('proyectos.administracion_proyecto'))
             
            form.nombre.data = proyecto_seleccionado.nombre  
            form.costo.data = proyecto_seleccionado.costo
            form.presupuesto.data = proyecto_seleccionado.presupuesto    
            form.fecha_inicio.data = proyecto_seleccionado.fecha_inicio
            form.fecha_fin.data = proyecto_seleccionado.fecha_fin 
            return render_template("proyecto/modificar_proyecto.html", form =  form)  
        else:  
            flash('El proyecto no puede ser modificado') 
            return redirect(url_for('proyectos.administracion_proyecto'))

    else:
        flash('NO TIENE PERMISOS PARA MODIFICAR EL PROYECTO SELECCIONADO') 
        return redirect(url_for('proyectos.administracion_proyecto'))




@mod.route('/consultar/<proyecto>/', methods=['GET', 'POST'])
def consultar_proyecto(proyecto):
    """
        Muestra todos los datos relacionados a un proyecto.
        
        @param proyecto: id del proyecto que se desea consultar.
    """
    #obtenemos el formulario
    form = ProyectoConsultar(request.form) 
    #obtenemos el proyecto seleccionado
    proyecto_seleccionado = Proyecto.query.filter_by(id=proyecto).first()
    #obtenemos el lider del proyecto
    liderProyecto = Usuario.query.get(proyecto_seleccionado.lider_id)
    #obtenemos las fases del proyecto seleccionado
    fases = Fase.query.filter(Fase.proyecto==proyecto_seleccionado)
    lista_fases=[]
    for fase in fases:
        lista_fases.append((fase.id,fase.nombre))
        
    lista_miembros=[]
    for miembro in proyecto_seleccionado.miembros:
        lista_miembros.append((miembro.id,miembro.nombre))
    
    form.nombre.data = proyecto_seleccionado.nombre 
    form.estado.data = proyecto_seleccionado.estado  
    form.costo.data = proyecto_seleccionado.costo
    form.presupuesto.data = proyecto_seleccionado.presupuesto    
    form.fecha_inicio.data = proyecto_seleccionado.fecha_inicio
    form.fecha_fin.data = proyecto_seleccionado.fecha_fin   
    form.lideres.data = liderProyecto.nombre
    form.fases.choices = lista_fases
    form.miembros.choices = lista_miembros
    return render_template("proyecto/consultar_proyecto.html", form =  form) 
    

@mod.route('/seleccionar/<proyecto>/', methods=['GET', 'POST'])
def seleccionar_miembros(proyecto):
    """
        Muestra una lista de usuarios que podran ser asignados y desasignados al proyecto.
        
        @param proyecto: id del proyecto al que se asignaran miembros.
    """
    
    if(verificar_autorizacion(g.user, g.proyecto,  'MODIFICAR')): 
        #obtenemos el proyecto seleccionado
        proyecto_seleccionado = Proyecto.query.filter_by(id=proyecto).first()
            
        if(proyecto_seleccionado.estado != 'Finalizado' and proyecto_seleccionado.estado != 'Cancelado' ):
            # Obtenemos el formulario
            form = ProyectoMiembros(request.form)
            # Obtenemos todos los usuarios activos existentes en la base de datos
            usuarios =Usuario.query.filter(Usuario.estado != 'INACTIVO')
            # Hacemos una tupla con el nombre y el id del usuario
            lista_usuarios=[]
            for usuario in usuarios:
                lista_usuarios.append((usuario.id, usuario.nombre))
                    
            # Asignamos la tupla de usuarios a la lista que va a ser visualizada en el checkbox  
            form.miembros.choices = lista_usuarios
                
            if form.validate_on_submit():
                                    
                # Obtenemos los miembros seleccionados para el proyecto
                lista_miembros = []
                for id_miembro in form.miembros.data:    
                    miembro  = Usuario.query.filter_by(id=id_miembro ).first()
                    lista_miembros.append(miembro )
                            
                #actualizamos los miembros para el proyecto
                proyecto_seleccionado.setMiembros(lista_miembros)
                db.session.add(proyecto_seleccionado)
                db.session.commit()
                flash('Se ha actualizado con exito los datos de miembros para el proyecto seleccionado')
                return redirect(url_for('proyectos.administracion_proyecto'))
                
            form.proyecto.data = proyecto_seleccionado.nombre
            #obtenemos los miembros que el proyecto ya tiene asignado
            miembros_act = []
            for miembro_sec in proyecto_seleccionado.miembros:
                miembros_act.append(miembro_sec.id)
            #mostramos seleccionados en el checkbox los miembros que posee el proyecto
            form.miembros.data =  miembros_act
            return render_template("proyecto/seleccionar_miembros.html", form =  form)        
        else:  
                flash('No se pueden asignar ni desasignar miembros para el proyecto.'
                + 'El proyecto se encuentra con estado Cancelado o Finalizado') 
                return redirect(url_for('proyectos.administracion_proyecto'))
    else:
        flash('NO TIENE PERMISOS PARA ASIGNARM MIEMBROS AL PROYECTO SELECCIONADO') 
        return redirect(url_for('proyectos.administracion_proyecto'))

def verificar_autorizacion(usuario = None, proyecto = None, permisoRequerido = None):
    """
        Verifica que el usuario tenga los permisos para realizar la accion indicada sobre una entidad seleccionada.
        
        @param usuario: el id del usuario que desea realizar la accion.
        @param proyecto: el proyecto en el cual se desea realizar la accion.
        @param permisoRequerido: el permiso que se requiere para realizar la accion. 
        
        @return autorizado: un boolean que indica si el usuario puede realizar la acccion. 
                            True si el usuario tiene el permiso requerido.
                            False si el usuario no tiene el permiso requerido.
    """
    
    autorizado = False
    
    rolAdministrador = db.session.query(Rol).filter_by(nombre = 'Administrador de Sistema').first()
   
    if rolAdministrador in usuario.roles:
            autorizado = True
            
    else:         
        permiso = db.session.query(Permiso).filter_by(nombre = permisoRequerido, entidad_id = proyecto.entidad_id).first()
       
        if(permiso != None):
            for rol in usuario.roles:
                if permiso in rol.permiso:
                    autorizado = True
    
    return autorizado
                
